import json
import os
import glob
import requests
import re
from bs4 import BeautifulSoup
from moviepy.editor import VideoFileClip
from django.core.management.base import BaseCommand
from django.utils.timezone import make_aware
from datetime import timedelta, datetime

from selenium.common import TimeoutException

from videoBox.models import Category, VideoSeries, VideoEpisode, Resource
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager


class CategoryScraper:
    """
    爬取整个类目的信息，包括类别、封面图、详情等。
    """

    def __init__(self, driver):
        self.driver = driver

    def load_categories(self):
        """加载 categories 配置文件"""
        with open("videoBox/configs/categories_config.json", "r", encoding="utf-8") as file:
            return json.load(file)

    def get_category_info(self, category_name):
        search_url = f'https://www.baidu.com/s?wd={category_name} 类型'
        self.driver.get(search_url)

        try:
            WebDriverWait(self.driver, 5).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, "div.c-container"))
            )
            text_content = ' '.join([e.text for e in self.driver.find_elements(By.CSS_SELECTOR, "div.c-container")])

            categories = self.load_categories()

            for main_cat, data in categories.items():
                for sub_cat in data["subcategories"].keys():
                    if sub_cat in text_content:
                        return main_cat, sub_cat

        except Exception as e:
            print(f"爬取类别失败: {e}")

        return '未知', '未知'

    def close(self):
        pass  # 不需要关闭 driver，因为由 VideoProcessor 管理


class BiliBiliScraper:
    """
    使用 Selenium 爬取 B 站上的视频详情信息。
    """

    def __init__(self, driver):
        self.driver = driver

    def get_video_details(self, video_title):
        search_url = f'https://search.bilibili.com/all?keyword={video_title}'
        self.driver.get(search_url)

        try:
            # 等待搜索结果加载
            WebDriverWait(self.driver, 10).until(
                EC.visibility_of_element_located((By.CSS_SELECTOR, "div.media-item"))
            )

            results = self.driver.find_elements(By.CSS_SELECTOR, "div.media-item")
            if not results:
                print(f"搜索无结果: {video_title}")
                return None, None, None

            result = results[0]  # 取第一个搜索结果
            title = result.find_element(By.CSS_SELECTOR, "a.text_ellipsis").text
            cover = result.find_element(By.CSS_SELECTOR, "img").get_attribute("src")

            desc_element = result.find_elements(By.CSS_SELECTOR, "div.media-card-content-head-text")
            desc = "\n".join([desc.text for desc in desc_element]) if desc_element else '暂无简介'

            return title, cover, desc

        except Exception as e:
            print(f"抓取数据错误: {e}")

        print(f"获取 B 站信息失败: {video_title}")
        return None, None, None

    def close(self):
        pass  # 不需要关闭 driver，因为由 VideoProcessor 管理


class VideoProcessor:
    """
    处理本地视频文件，并匹配爬取的类别、封面图、详情。
    """

    def __init__(self, video_path):
        self.video_path = video_path

        # 创建一个共享的 WebDriver 实例
        chrome_options = Options()
        chrome_options.add_argument("--headless")
        chrome_options.add_argument("--disable-gpu")
        chrome_options.add_argument("--window-size=1920,1080")
        chrome_options.add_argument("--disable-blink-features=AutomationControlled")
        chrome_options.binary_location = r"C:\Users\Administrator\AppData\Local\Google\Chrome\Bin\chrome.exe"

        self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=chrome_options)

        # 初始化爬虫类并传入共享的 driver
        self.category_scraper = CategoryScraper(self.driver)
        self.bili_scraper = BiliBiliScraper(self.driver)

    def process_videos(self):
        video_files = glob.glob(os.path.join(self.video_path, '**/*.*'), recursive=True)

        series_cache = {}  # 缓存已创建的 VideoSeries

        for video_file in video_files:
            video_dir = os.path.basename(os.path.dirname(video_file))
            video_name = os.path.basename(video_file)

            # 如果该目录的 VideoSeries 还未创建，则爬取数据
            if video_dir not in series_cache:
                # 爬取类别信息（仅执行一次）
                main_category, sub_category = self.category_scraper.get_category_info(video_dir)

                # 爬取 B 站视频信息（仅执行一次）
                title, cover, description = self.bili_scraper.get_video_details(video_dir)

                # 获取或创建类别
                category, _ = Category.objects.get_or_create(name=main_category)

                # 创建 VideoSeries（仅执行一次）
                video_series, _ = VideoSeries.objects.get_or_create(
                    title=title or video_dir,
                    category=category,
                    subcategory=sub_category if sub_category != '未知' else None,
                    defaults={
                        'description': description or "暂无简介",
                        'cover_image': cover,
                        'status': 'ongoing'  # 默认是连载状态
                    }
                )

                # 缓存该目录的 VideoSeries
                series_cache[video_dir] = video_series
            else:
                # 复用已经创建的 VideoSeries
                video_series = series_cache[video_dir]

            # 解析集数
            episode_number = self.get_episode_number(video_name)

            # 读取视频时长
            try:
                video_clip = VideoFileClip(video_file)
                duration = timedelta(seconds=video_clip.duration)
                video_clip.close()
            except Exception as e:
                print(f"读取视频时长失败: {video_name}, 错误: {e}")
                duration = timedelta(seconds=0)

            # 创建 VideoEpisode
            episode, _ = VideoEpisode.objects.get_or_create(
                series=video_series,
                episode_number=episode_number,
                defaults={
                    'title': f"{video_series.title} - 第 {episode_number} 集",
                    'video_url': f"/media/{video_name}",
                    'duration': duration,
                    'aired_date': make_aware(datetime.today()),
                    'views_count': 0
                }
            )

            # 创建资源信息
            Resource.objects.get_or_create(
                episode=episode,
                resource_url=f"/media/{video_name}",
                resource_type="高清",
                quality=self.get_video_quality(video_file),
                file_size=os.path.getsize(video_file),
                resource_name=video_name
            )

    def get_episode_number(self, video_name):
        match = re.search(r'\d+', video_name)
        return int(match.group()) if match else 1

    def get_video_quality(self, video_file):
        clip = VideoFileClip(video_file)
        width = clip.size[0]
        clip.close()

        if width >= 3840:
            return "4K"
        elif width >= 1920:
            return "1080p"
        elif width >= 1280:
            return "720p"
        else:
            return "480p"

    def close(self):
        # 关闭共享的 WebDriver 实例
        self.driver.quit()


class Command(BaseCommand):
    help = '初始化视频资源信息'

    def add_arguments(self, parser):
        parser.add_argument('video_path', type=str, help='视频文件夹路径')

    def handle(self, *args, **kwargs):
        video_path = kwargs['video_path']
        processor = VideoProcessor(video_path)
        processor.process_videos()
        processor.close()  # 在处理完成后关闭 WebDriver 实例
        self.stdout.write(self.style.SUCCESS("视频初始化完成"))
